package com.cygsunri.consumption.task;

import com.cygsunri.common.constant.DataName;
import com.cygsunri.common.service.CommonDataService;
import com.cygsunri.consumption.entity.Branch;
import com.cygsunri.consumption.entity.enumerate.EnergySort;
import com.cygsunri.consumption.service.BranchService;
import com.cygsunri.consumption.service.BuildingService;
import com.cygsunri.measurement.calculate.AbstractComplexEndureCalculateService;
import com.cygsunri.measurement.entity.MeasurementValue;
import com.cygsunri.rbac.entity.Account;
import com.cygsunri.rbac.service.AccountService;
import com.cygsunri.scada.service.ScadaMeasurementService;
import com.cygsunri.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 计算用户管理的建筑各种能耗合计
 */
@Component
@Slf4j
@ConditionalOnProperty(prefix = "task.consumption.account", name = "open", havingValue = "true")
@PropertySource(name = "application.yml", value = {"classpath:application.yml"}, ignoreResourceNotFound = false, encoding = "UTF-8")
public class ConsumptionCalcTask extends AbstractComplexEndureCalculateService {

    @Autowired
    private AccountService accountService;

    @Autowired
    private BuildingService buildingService;

    @Autowired
    private CommonDataService commonDataService;

    @Autowired
    private ScadaMeasurementService scadaMeasurementService;

    @Autowired
    private BranchService branchService;

    @Value("${task.consumption.account.original}")
    private int original;

    //private Map<Account, List<Building>> buildingMap = new HashMap<>();

    private Map<String, List<EnergySort>> energyMap = new HashMap<>();

    @Bean
    public void consumptionCalcInit() {
        List<Account> accounts = accountService.getAccountList();
        for (Account account : accounts) {
            //buildingMap.put(account, buildingService.getBuildingByAccount(account.getId()));
            energyMap.put(account.getId(), buildingService.getAccountEnergySort(account.getId()));
        }
    }

    //招商局采用总电表计算合计值
    /*@Scheduled(cron = "${task.consumption.account.cron}")
    private void consumptionCalc() {
        long a = System.currentTimeMillis();

        buildingMap.forEach((account, buildings) -> {
            List<EnergySort> energySorts = energyMap.get(account.getId());
            energySorts.forEach(energySort -> {
                //energySort.getName()作为计算量dataName
                if (!this.getNeedEndureCalculate(account.getPsrID(), account.getRealName(), energySort.getName())) {
                    return;
                }

                ImmutablePair<String, Integer> pair = scadaMeasurementService.getMeasurementID(account.getPsrID(), energySort.getName());
                if (pair == null) {
                    return;
                }

                Double sum = 0d;
                int num = 0;
                for (Building building : buildings) {
                    ImmutablePair<String, Integer> buildingPair = scadaMeasurementService.getMeasurementID(building.getPsrID(), energySort.getName());
                    if (buildingPair == null) {
                        continue;
                    }
                    MeasurementValue m = commonDataService.getValue(building.getPsrID(), energySort.getName());
                    if (!m.isInValid() && m.getData() != null) {
                        sum += m.getData();
                        num++;
                    }
                }

                if (num > 0) {
                    saveMean(pair.getLeft(), sum, DateUtil.nowMilliSeconds(), MeasurementValue.Quality.Calc.getKey());
                }
            });
        });

        //log.info("用户计算量共耗时：{} ms", System.currentTimeMillis() - a);
    }*/


    /**
     * 招商局采用总表计算合计值
     */
    @Scheduled(cron = "${task.consumption.account.cron}")
    private void consumptionCalc() {
        long a = System.currentTimeMillis();
        energyMap.forEach((account, energySorts) -> {
            energySorts.forEach(energySort -> {
                accountEnergySortCalc(account, energySort);
                accountEnergySortCalc(account, energySort,DataName.YEAR_ELECTRICITY);
                accountEnergySortCalc(account, energySort,DataName.YEAR_WATER);
            });
        });
        //log.info("用户计算量共耗时：{} ms", System.currentTimeMillis() - a);
    }

    /**
     * 年能耗计算
     */
    private void accountEnergySortCalc(String accountID, EnergySort energySort,String dataName) {
        Account account = accountService.getAccountByID(accountID);
        //energySort.getName()作为计算量dataName
        if (!this.getNeedEndureCalculate(account.getPsrID(), account.getRealName(), dataName)) {
            return;
        }

        ImmutablePair<String, Integer> pair = scadaMeasurementService.getMeasurementID(account.getPsrID(), dataName);
        if (pair == null) {
            return;
        }
        MeasurementValue m = commonDataService.getValue(account.getPsrID(), energySort.getName(),DateUtil.nowMilliSeconds(),503);
        if (!m.isInValid() && m.getData() != null) {
            saveMean(pair.getLeft(), m.getData(), DateUtil.nowMilliSeconds(), MeasurementValue.Quality.Calc.getKey());
        }

    }

    /**
     * 总能耗计算
     */
    private void accountEnergySortCalc(String accountID, EnergySort energySort) {
        Account account = accountService.getAccountByID(accountID);
        //energySort.getName()作为计算量dataName
        if (!this.getNeedEndureCalculate(account.getPsrID(), account.getRealName(), energySort.getName())) {
            return;
        }

        ImmutablePair<String, Integer> pair = scadaMeasurementService.getMeasurementID(account.getPsrID(), energySort.getName());
        if (pair == null) {
            return;
        }

//        //得到没有关联建筑的总表
//        List<Branch> branches = branchService.getBranchesByEnergySortWithOutBuilding(energySort.getName());
//        Double sum = 0d;
//        int num = 0;
//        for (Branch branch : branches) {
//            MeasurementValue m = commonDataService.getValue(branch.getPsrID(), energySort.getName());
//            if (!m.isInValid() && m.getData() != null) {
//                sum += m.getData();
//                num++;
//            }

        //得到关联建筑的总表
        List<Branch> branches = branchService.getBranchesByEnergySortWithBuilding(energySort.getName());
        Double sum = 0d;
        int num = 0;
        for (Branch branch : branches) {
            MeasurementValue m = commonDataService.getValue(branch.getPsrID(), energySort.getName());
            if (!m.isInValid() && m.getData() != null) {
                sum += m.getData();
                num++;
            }
//            //招商局定制：电能耗减去反向电量再加上逆变器发电量
//            if (energySort.getKey() == 0) {
//                MeasurementValue r = commonDataService.getValue(branch.getPsrID(), DataName.REVERSE_ELECTRICITY);
//                if (!r.isInValid() && r.getData() != null) {
//                    sum -= r.getData();
//                    num++;
//                }
//            }

        }

//        //安徽吉电定制：电能耗加上风电发电量
//        if (energySort.getKey() == 0) {
//            MeasurementValue s = commonDataService.getValue("Swind", DataName.TOTAL_GENERATED);
//            if (!s.isInValid() && s.getData() != null) {
//                sum += s.getData();
//                num++;
//            }
//        }
//
//        //安徽吉电定制：电能耗加上光伏发电量
//        if (energySort.getKey() == 0) {
//            MeasurementValue s = commonDataService.getValue("Ssolar", DataName.TOTAL_GENERATED);
//            if (!s.isInValid() && s.getData() != null) {
//                sum += s.getData();
//                num++;
//            }
//        }

        if (num > 0) {
            saveMean(pair.getLeft(), sum, DateUtil.nowMilliSeconds(), MeasurementValue.Quality.Calc.getKey());
        }
    }
}
